#include <iostream>
#include <string>
#include <mysql/mysql.h>
// using namespace std;
const std::string host = "127.0.0.1"; // 也可以写成 localhost
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn"; // 访问的数据库
const unsigned int port = 8080;

int main()
{
    // std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;
    // return 0;

    // 创建MYSQL对象并初始化
    MYSQL *my = mysql_init(nullptr);
    // 初始化成功就不会返回bullptr
    if (my == nullptr)
    {
        std::cerr << "初始化 MYSQL 失败" << std::endl;
        return 1;
    }

    // 连接mysql服务器，利用mysql_real_connect,执行失败返回nullptr
    //     MYSQL * mysql_real_connect(MYSQL *mysql,
    //                    const char *host,
    //                    const char *user,
    //                    const char *passwd,
    //                    const char *db,
    //                    unsigned int port,
    //                    const char *unix_socket,  //域间套接字
    //                    unsigned long client_flag)

    if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        // 连接失败
        std::cerr << "connect MYSQL 失败：" << mysql_error(my) << std::endl;
        return 2;
    }
    // std::cout << "connect MYSQL success " << std::endl;
    // 需要将客户端与服务器端的编码进行统一，服务器端使用的是utfbmb4;利用函数：mysql_set_character_set
    mysql_set_character_set(my, "utf8mb4");

    // std::string sql;
    // 下达指令通过 mysql_query 来实现,成功返回0失败返回非0
    // while(true)
    // {
    //     std::cout << "MYSQL>>>>";
    //     if(!getline(std::cin ,sql) || sql=="quit")
    //     {
    //         std::cout << "bye bye~" << std::endl;
    //         break;
    //     }
    //     //将合法的指令进行处理
    //     int n = mysql_query(my,sql.c_str());
    //     //判断返回值
    //     if(n==0)
    //     {
    //         std::cout << sql << " success : " << n << std::endl;
    //     }
    //     else
    //     {
    //         std::cerr << sql << " failed : " << n << std::endl;
    //     }
    // }
    // 根据需求下达指令，不实现为循环
    // std::string sql = "insert into user (name,age,telphone) values ('赵六',32 ,123719121)";
    std::string sql = "select * from user";
    int n = mysql_query(my, sql.c_str());
    if (n == 0)
    {
        std::cout << sql << " success : " << n << std::endl;
    }
    else
    {
        std::cerr << sql << " failed : " << n << std::endl;
        return 3;
    }

    // select 执行过后的结果保存再MYSQL对象中，需要调用mysql_store_result 函数将MYSQL中保存的数据转储到结构MYSQL_RES中
    //MYSQL_RES会以行为单位将查询出来的表结构组织好；表结构是格式化输出打印出来的，mysql真正存储的数据为列属性以及其所对应的数据
    //再利用 mysql_num_rows 获取有多少行的信息，利用mysql_num_fields 获取有多少列的信息； mysql_fetch_fields 获取列名
    //mysql_fetch_row 获取每一行的数据，会返回MYSQL_ROW对象，当做数组访问便可
    // MYSQL_RES * mysql_store_result(MYSQL *mysql);
    // uint64_t mysql_num_rows(MYSQL_RES *result);
    // unsigned int mysql_num_fields(MYSQL_RES *result);
    // MYSQL_FIELD * mysql_fetch_field(MYSQL_RES *result);
    // MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    MYSQL_RES * res = mysql_store_result(my);
    if(res == nullptr)
    {
        std::cerr << "mysql_store_result 执行失败" << std::endl;
        return 4;
    }

    //获取行数与列信息
    int rows = mysql_num_rows(res);
    int fields = mysql_num_fields(res);

    //打印列的信息
    MYSQL_FIELD * fields_array = mysql_fetch_fields(res);//MYSQL_FIDLE 是一个结构体
    for(int i = 0;i < fields;i++)
    {
        std::cout << fields_array[i].name << '\t';
    }
    std::cout << '\n';

    //打印每一行
    for(int i = 0;i<rows;i++)
    {
        MYSQL_ROW row = mysql_fetch_row(res);//获取每一行的信息，typedef char **MYSQL_ROW 将row 当做一个二位数组
        for(int j = 0;j<fields;j++)
        {
            std::cout << row[j] << "\t";
        }
        std::cout << "\n";
    }
    //最后，MYSQL_RES这样的变量会调用malloc 开辟空间，我们使用结束之后记得将空间进行释放，调用mysql_free_result 
    mysql_free_result(res);
    
    // 使用完毕使用mysql_close 关闭
    mysql_close(my);
    return 0;
}